package tt.dz.biz.service.task;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tt.dz.biz.annotation.MsLog;
import tt.dz.biz.dao.common.CommonDAO;
import tt.dz.biz.dao.merch.BalanceCheckDAOImp;
import tt.dz.biz.dao.merch.ChangeDayDAOImp;
import tt.dz.biz.dao.merch.MerchAccountDetailDAOImp;
import tt.dz.common.DateUtil;
import tt.dz.common.DzConstants;
import tt.dz.common.DzConstants.BizType;
import tt.dz.common.DzConstants.curBalType;
import tt.dz.common.LogUtil;
import tt.dz.vo.BalanceCheckVO;
import tt.dz.vo.ChangeDayVO;

@Service("merchAccountDetailService")
public class MerchAccountDetailService
{
  @Resource(name="merchAccountDetailDAO")
  MerchAccountDetailDAOImp merchAccountDetailDAO;
  @Resource(name="changeDayDAO")
  ChangeDayDAOImp changeDayDAO;
  @Resource(name="commonDAO")
  CommonDAO commonDAO;
  @Resource(name="balanceCheckDAO")
  BalanceCheckDAOImp balanceCheckDAO;
  
  @MsLog(bizCode="merchAccountJob", bizName="运营商日切相关JOB", bizType=DzConstants.BizType.JOB, bizDesc="此JOB包含日记账、试算平衡、日切")
  public void executeMerchAccountJob()
    throws Exception
  {
    try
    {
      if (beforeExecuteMerchAccountJob())
      {
        executeDayAccountJob();
        
        executeBalanceCheckJob();
        
        executeDayChangeJob();
      }
      else
      {
        LogUtil.info("日切相关JOB今日已在其他服务器上运行");
      }
    }
    catch (Exception e)
    {
      LogUtil.error("执行日记账、试算平衡、日切JOB发生异常！", e);
      throw e;
    }
  }
  
  private boolean beforeExecuteMerchAccountJob()
    throws Exception
  {
    Date updateDate = this.changeDayDAO.getUpdateDateByChangeDay();
    
    Date currentDBTime = this.commonDAO.getDBCurrentTime();
    if ((updateDate != null) && (currentDBTime != null))
    {
      DateFormat sf = new SimpleDateFormat("yyyyMMdd");
      int d1 = Integer.valueOf(sf.format(updateDate)).intValue();
      int d2 = Integer.valueOf(sf.format(currentDBTime)).intValue();
      if (d2 - d1 >= 1) {
        return true;
      }
      return false;
    }
    return true;
  }
  
  public void executeDayAccountJob()
    throws Exception
  {
    LogUtil.info("日记账JOB执行开始");
    
    Date accountingDate = this.changeDayDAO.queryAccountingDateForChangeDay();
    Assert.notNull(accountingDate, "查询会计账务日期为空，请检查！");
    LogUtil.debug("会计账务日期：" + accountingDate);
    try
    {
      this.merchAccountDetailDAO.accountDividendToDetail(accountingDate);
    }
    catch (Exception e)
    {
      LogUtil.error("日记账JOB发生异常", e);
      throw e;
    }
    LogUtil.info("日记账JOB执行完成");
  }
  
  public void executeDayChangeJob()
    throws Exception
  {
    LogUtil.info("日切JOB执行开始");
    ChangeDayVO changeDayVo = this.changeDayDAO.queryChangeDay();
    Assert.notNull(changeDayVo, "查询日切对象为空，请检查！");
    Date tmrAccountingDate = changeDayVo.getTmrAccountingDate();
    Calendar tmrAccountingCalendar = Calendar.getInstance();
    tmrAccountingCalendar.setTime(tmrAccountingDate);
    tmrAccountingCalendar.set(5, tmrAccountingCalendar.get(5) + 1);
    changeDayVo.setYtdAccountingDate(changeDayVo.getAccountingDate());
    changeDayVo.setAccountingDate(changeDayVo.getTmrAccountingDate());
    changeDayVo.setTmrAccountingDate(tmrAccountingCalendar.getTime());
    changeDayVo.setUpdatedDate(DateUtil.getDBCurrentTime());
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    LogUtil.debug("日切昨天：" + df.format(changeDayVo.getAccountingDate()));
    LogUtil.debug("日切账务日期：" + df.format(changeDayVo.getTmrAccountingDate()));
    LogUtil.debug("日切明天：" + df.format(tmrAccountingCalendar.getTime()));
    LogUtil.debug("日切表VO：" + changeDayVo);
    try
    {
      this.changeDayDAO.updteSubjectAccLastBal();
      Date now = this.commonDAO.getDBCurrentTime();
      if (now != null) {
        changeDayVo.setUpdatedDate(now);
      }
      this.changeDayDAO.updateChangeDay(changeDayVo);
    }
    catch (Exception e)
    {
      LogUtil.error("日切JoB发生异常", e);
      throw e;
    }
    LogUtil.info("日切JOB执行完成");
  }
  
  public void executeBalanceCheckJob()
    throws Exception
  {
    LogUtil.info("试算平衡JOB执行开始");
    
    Date accountingDate = this.changeDayDAO.queryAccountingDateForChangeDay();
    Assert.notNull(accountingDate, "查询会计账务日期为空，请检查！");
    LogUtil.debug("会计账务日期：" + accountingDate);
    Map<String, BigDecimal> DetailChangeMap = new HashMap();
    List<BalanceCheckVO> balanceCheckList = new ArrayList();
    
    List<Map<String, Object>> DetailChangeList = this.merchAccountDetailDAO.queryChangeAmountForDetailByAccountingDate(accountingDate);
    LogUtil.debug("运营商内部帐户明细表数据记录数：" + (DetailChangeList != null ? DetailChangeList.size() : 0));
    List<Map<String, Object>> subjectAccChangeList = this.merchAccountDetailDAO.queryChangeAmountForSubjectAcc();
    LogUtil.debug("运营商内部帐户信息表数据记录数：" + (subjectAccChangeList != null ? subjectAccChangeList.size() : 0));
    for (Map<String, Object> DetailChangerow : DetailChangeList)
    {
      String merchantCode = (String)DetailChangerow.get("merchantCode");
      String subSubjectCode = (String)DetailChangerow.get("subSubjectCode");
      BigDecimal changeAmount = (BigDecimal)DetailChangerow.get("changeAmount");
      String key = merchantCode + "`" + subSubjectCode;
      DetailChangeMap.put(key, changeAmount);
    }
    LogUtil.debug("运营商内部帐户明细表数据Map加工完成，记录数：" + DetailChangeMap.size());
    for (Map<String, Object> subjectAccChangerow : subjectAccChangeList)
    {
      BalanceCheckVO balanceCheckVo = new BalanceCheckVO();
      String merchantCode = (String)subjectAccChangerow.get("merchantCode");
      String subSubjectCode = (String)subjectAccChangerow.get("subSubjectCode");
      BigDecimal subjectAmount = (BigDecimal)subjectAccChangerow.get("changeAmount");
      String key = merchantCode + "`" + subSubjectCode;
      BigDecimal dailyAmount = (BigDecimal)DetailChangeMap.get(key);
      dailyAmount = dailyAmount != null ? dailyAmount : BigDecimal.ZERO;
      subjectAmount = subjectAmount != null ? subjectAmount : BigDecimal.ZERO;
      balanceCheckVo.setMerchantCode(merchantCode);
      balanceCheckVo.setSubSubjectCode(subSubjectCode);
      balanceCheckVo.setDailyAmount(dailyAmount);
      balanceCheckVo.setSubjectAmount(subjectAmount);
      balanceCheckVo.setAccountingDate(accountingDate);
      if (dailyAmount.compareTo(subjectAmount) == 0) {
        balanceCheckVo.setCurBal(DzConstants.curBalType.BALANCE.value());
      } else {
        balanceCheckVo.setCurBal(DzConstants.curBalType.UNBALANCE.value());
      }
      balanceCheckList.add(balanceCheckVo);
    }
    LogUtil.debug("试算平衡数据装配完成，记录数：" + balanceCheckList.size());
    try
    {
      this.balanceCheckDAO.insertBatchBalanceCheck(balanceCheckList);
    }
    catch (Exception e)
    {
      LogUtil.error("写入试算平衡发生异常!" + e);
      throw e;
    }
    LogUtil.info("试算平衡JOB执行完成");
  }
}
